package cate.game.play.skill;


import cate.common.table.d.GDBuff;
import cate.common.table.d.GDSkill;
import cate.common.util.XT;
import cate.game.play.buff.Buff;
import cate.game.play.buff.BuffHandler;
import cate.game.play.fighter.Fighter;
import cate.game.play.proce.round.RoundCtx;
import easy.java.dev.note.NoteClass;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


@NoteClass("技能选择器")
public class SkillSelector {

    public static Skill select(RoundCtx round, Fighter fighter) {
        Skill skill = doSelect(round, fighter);
        handleSkillCD(round,fighter);
        //skill = handleTempReplace(round,fighter,skill);
        return skill;
    }

    private static Skill doSelect(RoundCtx round, Fighter fighter) {
        //禁用普攻
        boolean noAttack = fighter.buff.containType(GDBuff.Type.缴械);
        //禁用主动
        boolean noActive = fighter.buff.containType(GDBuff.Type.沉默);

        //混乱状态下强制使用普攻（嘲讽、恐惧）
        if (fighter.buff.isChaos()) {
            if (noAttack) {
                return null;
            } else {
                return handleForceUseAttack(round,fighter);
            }
        }
        //技能选取
        for (Skill s : selectByCd(round, fighter)) {
            //检测技能是否被限制释放
            if (noAttack && s.cfg.row.type == GDSkill.Type.ATTACK) {
                continue;
            }
            if (noActive && s.cfg.row.type == GDSkill.Type.ACTIVE) {
                continue;
            }
            return s;
        }
        return null;
    }

    /**
     * cd记录 （不管放不放技能都进cd）
     * @param round
     * @param fighter
     */
    public static void handleSkillCD(RoundCtx round, Fighter fighter) {
        for (Skill s : fighter.skill.getAllActive()) {
            if (!fighter.cd.available(s, round.index)) {
                continue;
            }
            //技能满足cd的都要记录下
            fighter.cd.handleSkillCD(s, round.index);
        }
    }

    /**
     * 只根据cd选取技能（忽略各种限制情况）
     * @param round
     * @param fighter
     * @return
     */
    private static List<Skill> selectByCd(RoundCtx round, Fighter fighter) {
        List<Skill> skillList = new ArrayList<>();
        for (Skill s : fighter.skill.getAllActive()) {
            if (!fighter.cd.available(s, round.index)) {
                continue;
            }
            skillList.add(s);
        }
        skillList.sort(Comparator.comparingInt(s -> -s.cfg.row.usePriority));
        return skillList;
    }

    public static Skill selectOneByCd(RoundCtx round, Fighter fighter){
        List<Skill> skillList = selectByCd(round,fighter);
        if(XT.isNotBlank(skillList)){
            return skillList.get(0);
        }
        return null;
    }

    /**
     * 混乱状态下强制使用普攻
     * @param fighter
     * @return
     */
    private static Skill handleForceUseAttack(RoundCtx round,Fighter fighter) {
        Skill attack = fighter.skill.getAttack();
        if (attack == null) {
            return null;
        }
        for (BuffHandler h : fighter.buff.getHandlers()) {
            boolean use = h.forceUseAttack(round,attack);
            if (use) {
                return attack;
            }
        }
        return null;
    }

    public static Skill handleTempReplace(RoundCtx round, Fighter f, Skill skr) {
        if (skr == null) {
            return null;
        }
        Skill replaceSkr = null;
        for (Buff buff : f.buff.getValidBuffs()) {
            replaceSkr = buff.handler.handleReplace(round, skr);
            if (replaceSkr != null) {
                return replaceSkr;
            }
        }
        return skr;
    }
}
